<template>
  <div class="mapContainer">
    <div class="operation">
      <el-button type="primary" size="mini" @click="showDomain">新建安全域</el-button>
      <el-button type="primary" size="mini" @click="dialogDevice=true">新增设备</el-button>
      <el-button type="success" :loading="saveLoad" size="mini" @click="saveAll('/order/receiveOrderMsg',1)">保 存</el-button>
      <el-button type="success" :loading="applyLoad" size="mini" @click="saveAll('/order/executeOrder',0)">执 行</el-button>
    </div>
    <div id="myDiagramDiv"></div>
    <el-dialog
      title="新建安全域"
      :visible.sync="dialogVisible"
      width="30%">
        <el-form status-icon ref="security" label-width="100px" class="security">
          <el-form-item label="安全域名">
            <el-input type="text" v-model="security.key" autocomplete="off" readOnly></el-input>
          </el-form-item>
          <el-form-item label="选择虚机">
            <el-select v-model="vms" multiple placeholder="请选择">
                <el-option v-for="(n,i) in virtualDevice" :key="i" :label="n.instanceName" :value="n.instanceIp"></el-option>
              </el-select>
          </el-form-item>
        </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" size="small" @click="submitForm">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 这里是向安全域里添加额外的虚拟机 -->
      <el-dialog
        :title="`安全域:${addName}`"
        :visible.sync="addtionVM"
        width="30%">
          <el-form status-icon label-width="100px" class="security">
            <el-form-item label="添加虚机">
              <el-select v-model="vms" multiple placeholder="请选择">
                  <el-option v-for="(n,i) in virtualDevice" :key="i" :label="n.instanceName" :value="n.instanceIp"></el-option>
                </el-select>
            </el-form-item>
          </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button size="mini" @click="addtionVM = false">取 消</el-button>
          <el-button type="primary" size="mini" @click="addConfirm">确 定</el-button>
        </span>
      </el-dialog>
    <!-- 上面的代码块是向安全域里添加额外的虚拟机 -->
    <el-dialog
      title="新增设备"
      :visible.sync="dialogDevice"
      width="360px">
       <label>选择设备：</label>
        <el-select v-model="addDevice" multiple placeholder="请选择">
          <el-option label="防火墙" value="firewall"></el-option>
          <el-option label="VPN" value="vpn"></el-option>
        </el-select>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" @click="dialogDevice = false">取 消</el-button>
        <el-button type="primary" size="small" @click="submitAdd(addDevice)">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog
      :visible.sync="dialogDrawLink"
      width="30%">
      <span>您确定建立此连线关系吗？？？</span>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" @click="cancelLink">取 消</el-button>
        <el-button size="small" type="primary" @click="confirmLink">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog
      :visible.sync="dialogSelect"
      width="360px">
        <label class="dg_label">操作选择：</label>
        <el-select v-model="operation">
          <el-option label="编辑节点信息" :value="0"></el-option>
          <el-option label="创建关系连线" :value="1"></el-option>
        </el-select>
      <span slot="footer" class="dialog-footer">
          <el-button @click="dialogSelect = false">取 消</el-button>
          <el-button type="primary" @click="changeOperation(operation)">确 定</el-button>
      </span>
    </el-dialog>
    <EditorFire ref="fireWall" :allCreateVM="allCreateVM" :netWorkName="netWorkName" @fireData="fireData"></EditorFire>
    <EditorVpn ref="vpn" :allCreateVM="allCreateVM" :netWorkName="netWorkName" @vpnData="vpnData"></EditorVpn>
  </div>
</template>

<script>
import "@/assets/go.js"
import EditorFire from "./securityTopology/editorFirewall"
import EditorVpn from "./securityTopology/editorVPN"
import { init } from "@/assets/js/initTopology.js"
export default {
  name: 'HelloWorld',
  components: {
    EditorFire,
    EditorVpn
  },
  data() {
    return {
      addName: '',
      myDiagram: null,
      saveLoad: false,
      applyLoad: false,
      addtionVM: false,
      dialogVisible: false,
      dialogDevice: false,
      dialogDrawLink: false,
      dialogSelect: false,
      innerDialog: false,
      operation: 0,
      count: 0,
      virtualDevice: [],
      nodeArr: [],
      linkArr: [],
      netWorkName: [],
      allCreateVM: [],
      targetNode: {},
      vms: [],
      security: {
        key: '',
        vms: [],
        accessNetwork: null,
        cipherMachine: null,
        domainId: null,
        domainName: '',
        domainType: "0",
        elementCount: 1,
        state: null,
        stateMessage: null
      },
      addDevice: [],
      singleLink: {
        from: '',
        to: ''
      }
    }
  },
  watch: {
    myDiagram(val) {
      this.myDiagram.addDiagramListener("SelectionDeleting",(e) => {
        e.subject.each(n => {
          // n为删除节点或线的对象
          let O = n.data
          if(O.type=="service") {
            var nodeData = this.myDiagram.model.findNodeDataForKey(O.group)
            nodeData.vms.forEach((m,i) => {
              if(m.instanceIp == O.key) {
                nodeData.vms.splice(i,1)
              }
            })
            delete O.key
            delete O.type
            delete O.group
            this.virtualDevice.push(O)
            this.myDiagram.model.updateTargetBindings(nodeData)
          }else if(O.isGroup) {
            this.virtualDevice.push.apply(this.virtualDevice,O.vms);
          }
        })
      })
    }
  },
  mounted() {
    this.getnetwork()
    this.dataDocking()
    this.$http({
    	url: this.$http.adornUrl('/order/getAllResource'),
    	method: 'get',
    }).then(({data}) => {
      this.virtualDevice = data.instanceList
    }).catch(error => {
    	this.$message({
    		showClose: false,
    		message: '程序异常,请联系管理员',
    		type: 'warning'
    	})
    })
  },
  methods: {
    switchImg(node) {
      return require(`@/assets/img/element/${node.type}.jpg`)
    },
    saveAll(url,sta) {
      if(this.myDiagram) {
        sta ? this.saveLoad=true : this.applyLoad=true
        let obj = JSON.parse(this.myDiagram.model.toJson())
        let link = obj.linkDataArray, node = obj.nodeDataArray
        let start = link.filter(item => item.from.indexOf('D')>=0)[0]
        let end = link.filter(item => item.to.indexOf('D')>=0)[0]
        let orderLink = []
        let vnfs = []
        orderLink.push(start)
        for(let i=1;i<link.length;i++) {
          link.forEach(n => { if(n.from == orderLink[orderLink.length-1].to) orderLink.push(n) })
        }
        let flagArr = [...orderLink]
        flagArr.shift()
        flagArr.forEach(n => {
          let item = node.filter(m => m.key == n.from)[0]
          delete item.key
          delete item.type
          vnfs.push(item)
        })
        vnfs.map((n,i) => n.vnfIndex = i)
        let domains = node.filter(n => n.isGroup == true)
        domains.map(n => {
          delete n.key
          delete n.isGroup
          n.vms.map((item,i) => {
            let O = {
              vmId: item.instanceId,
              vmName: item.instanceName,
              cmpId: item.instanceIp
            }
            Object.assign(item,O)
            delete item.disabled
            delete item.instanceId
            delete item.instanceName
            delete item.instanceIp
          })
          // return n
        })
        let linkArr = []
        orderLink.forEach((n,i) => {
          let m = {
            startId: n.from,
            isStart: i==0,
            endId: n.to,
            isEnd: i == orderLink.length-1
          }
          linkArr.push(m)
        })
        let totleData = {
          actionType: 0,
          inuse: false,
          orderId: "",
          sequenceId: "",
          serviceId: null,
          state: "ACTIVE",
          stateMessage: null,
          updatetime: (new Date()).getTime(),
          userId: this.$store.state.user.id,
          chains: [{
            chainId: null,
            endDomainId: end.to,
            links: linkArr,
            startDomainId: start.from,
            state: null,
            stateMessage: null,
            vnfs: vnfs
          }],
          domains: domains
        }
        this.$http({
          url: this.$http.adornUrl(url),
          method: 'post',
          data: this.$http.adornData(totleData, false)
        }).then(({data}) => {
          this.$message({
            showClose: true,
            message: data.msg,
            type: 'warning'
          })
          sta ? this.saveLoad=false : this.applyLoad=false
        })
      }
    },
    fireData(obj) {
      let key = obj.firewall.firewallName
      var nodeData = this.myDiagram.model.findNodeDataForKey(key);
      nodeData.firewall = obj.firewall
      nodeData.createVM = obj.createVM
      this.myDiagram.model.updateTargetBindings(nodeData);
    },
    vpnData(obj) {
      let key = obj.vpn.vpnName
      var nodeData = this.myDiagram.model.findNodeDataForKey(key);
      nodeData.vpn = obj.vpn
      nodeData.createVM = obj.createVM
      this.myDiagram.model.updateTargetBindings(nodeData);
    },
    changeOperation(e) {
      if(e) {
        if(!this.singleLink.from) {
          this.singleLink.from = this.targetNode.key
          this.$message({
            showClose: true,
            message: '选中连线起点',
            type: 'info'
          })
        }
      } else {
        let O = this.targetNode
        if (O.type=="firewall") {
          this.$refs.fireWall.showDialog(this.targetNode.key)
        } else if (O.type=="vpn") {
          this.$refs.vpn.showVpn(this.targetNode.key)
        } else if(O.isGroup){
          this.addName = O.key
          this.addtionVM = true
        } else {
          this.$message({
            showClose: true,
            message: '此设备不可编辑',
            type: 'warning'
          })
        }
      }
      this.dialogSelect = false
    },
    addConfirm() {
      let node = []
      let target = this.myDiagram.model.findNodeDataForKey(this.addName);
      this.vms.forEach((item,i) => {
        this.virtualDevice.forEach((n,j) => {
          if(n.instanceIp == item) {
            let vm = Object.assign({},n,{key: item, type: 'service',group: target.key})
            node.push(vm)
            target.vms.push(n)
            this.virtualDevice.splice(j,1)
          }
        })
      })
      this.myDiagram.model.updateTargetBindings(target)
      let obj = JSON.parse(this.myDiagram.model.toJson())
      let linkArr = obj.linkDataArray, nodeArr = obj.nodeDataArray
      nodeArr.push(...node)
      this.nodeArr = nodeArr
      init(this,nodeArr,linkArr)
      this.vms = []
      this.addtionVM = false
    },
    submitAdd(a) {
      if(a.length) {
        let node = []
        a.forEach(item => {
          let id = (new Date()).getTime()
          let obj = {
            key: `${item=='firewall'?'W':'V'}${id}`,
            type: item,
            inPortId: 1,
            outPortId: 2,
            state: null,
            stateMessage: null,
            vnfId: `${item=='firewall'?'W':'V'}${id}`,
            vnfIndex: null,
            vnfType: item=='firewall'?'0':'1',
            vpn: null,
            createVM: null,
            firewall: null
          }
          node.push(obj)
        })
        this.nodeArr.push(...node)
        let allData = JSON.parse(this.myDiagram.model.toJson())
        let linkArr = allData.linkDataArray
        init(this,this.nodeArr, linkArr)
        this.addDevice = []
        this.dialogDevice = false
      } else {
        this.$message({
          showClose: true,
          message: '请添加设备',
          type: 'warning'
        });
      }
    },
    confirmLink() {
      this.myDiagram.model.addLinkData(this.singleLink)
      this.singleLink = {from: '',to: ''}
      this.dialogDrawLink = false
    },
    cancelLink() {
      this.singleLink = {
        from: '',
        to: ''
      }
      this.dialogDrawLink = false
    },
    showDomain() {
      let stamp = (new Date()).getTime()
      this.security.key = `D${stamp}`
      this.security.domainId = `D${stamp}`
      this.security.domainName = `D${stamp}`
      this.dialogVisible = true
    },
    submitForm() {

      if(!this.vms.length) {
        this.$message({
          showClose: true,
          message: '请添加虚机',
          type: 'warning'
        });
      } else {
        let node = []
        let obj = Object.assign({},this.security)
        obj.elementCount = this.vms.length
        obj.vms = []
        this.vms.forEach((item,i) => {
          this.virtualDevice.forEach((n,j) => {
            if(n.instanceIp == item) {
              let vm = Object.assign({},n,{key: item, type: 'service',group: obj.key})
              node.push(vm)
              obj.vms.push(n)
              this.virtualDevice.splice(j,1)
            }
          })
        })
        let mix = Object.assign({},obj,{isGroup:true})
        node.push(mix)
        this.nodeArr.push.apply(this.nodeArr,node)
        let allData = this.myDiagram ? JSON.parse(this.myDiagram.model.toJson()) : {}
        let linkArr = allData ? allData.linkDataArray : []
        init(this,this.nodeArr, linkArr)
        this.vms = []
        this.dialogVisible = false
      }
    },
    getnetwork() {
      this.$http({
        url: this.$http.adornUrl('/vm/networkList'),
        method: 'post'
      }).then(({data}) => {
        if (data.list && data.list.length) {
          this.netWorkName = data.list
        }
      }).catch(error => {
        this.$message({
          showClose: false,
          message: '程序异常,请联系管理员',
          type: 'warning'
        })
      })
    },
    dataDocking() { // 接口获取规则配置数据
      this.$http({
        url: this.$http.adornHardWareUrl('/generator/deploy/listAll'),
        method: 'get',
        params: this.$http.adornParams()
      }).then(({data}) => {
        if (data && data.code == '0') {
          this.allCreateVM = data.all
        }
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.mapContainer {
  .el-input {
    width: 220px;
  }
  .operation {
    width: 100%;
    height: 32px;
    .el-button {
      float: left;
      margin-right: 10px;
    }
  }
  #myDiagramDiv {
  	height: 500px;
  	width: 100%;
  }
  .dg_label {
    font: bold 16px/32px "微软雅黑";
  }
}
</style>
